package com.haizi.battery.service.battery.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.haizi.battery.entity.battery.BatteryLogDetail;
import com.haizi.battery.entity.battery.RealTimeData;
import com.haizi.battery.gate.core.evgb.entity.*;
import com.haizi.battery.gate.core.evgb.enumtype.ResponseType;
import com.haizi.battery.gate.server.common.CommonCache;
import com.haizi.battery.gate.server.handler.QueryHandler;
import com.haizi.battery.gate.server.handler.UpdateHandler;
import com.haizi.battery.mapper.battery.BatteryLogDetailMapper;
import com.haizi.battery.mapper.battery.RealTimeDataMapper;
import com.haizi.battery.service.battery.RealTimeDataService;
import com.haizi.battery.utils.R;
import io.netty.channel.Channel;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;

import static com.haizi.battery.gate.core.evgb.enumtype.CommandType.QUERY_COMMAND;
import static com.haizi.battery.gate.core.evgb.enumtype.CommandType.REMOTE_CONTROL;

/**
 * <p>
 *     储能站
 * </p>
 *
 * @author HaiziGe
 * @date 2020-07-27 16:19:04
 */
@Slf4j
@Service
public class RealTimeDataServiceImpl extends ServiceImpl<RealTimeDataMapper, RealTimeData> implements RealTimeDataService {

    @Autowired
    private UpdateHandler updateHandler;

    @Autowired
    private QueryHandler queryHandler;

    @Autowired
    private BatteryLogDetailMapper logDetailMapper;

    @Override
    public boolean save(RealTimeData entity) {

        LambdaQueryWrapper<RealTimeData> realTimeDataWrapper = Wrappers.lambdaQuery();
        realTimeDataWrapper.eq(RealTimeData::getVin, entity.getVin());
        Integer count = baseMapper.selectCount(realTimeDataWrapper);
        if (count > 0 ) {
            return false;
        }
        return retBool(baseMapper.insert(entity));
    }

    @Override
    public void updateByVin(RealTimeData realTimeData) {
        LambdaUpdateWrapper<RealTimeData> realTimeDataWrapper = Wrappers.lambdaUpdate();
        realTimeDataWrapper.eq(RealTimeData::getVin, realTimeData.getVin());
        baseMapper.update(realTimeData, realTimeDataWrapper);
        if(realTimeData.getOnline() < 1) {
            logDetailMapper.insert(new BatteryLogDetail(realTimeData));
        }
    }

    @Override
    public R updateTerminal(Integer id, UpdateBms updateBms) {
        RealTimeData data = this.getById(id);
        log.info(" vin {}", data.getVin());
        EvGBProtocol protocol = new EvGBProtocol();
        protocol.setVin(data.getVin());
        protocol.setCommandType(REMOTE_CONTROL);
        DataBody dataBody = new DataBody(updateBms.encode());
        dataBody.setJson((JSONObject) JSONObject.toJSON(updateBms));
        protocol.setBody(dataBody);
        protocol.setResponseType(ResponseType.COMMAND);
        log.info(" protocol {}", JSON.toJSON(protocol));
        updateHandler.doBusiness(protocol, CommonCache.vinChannelMap.get(data.getVin()));

        return R.ok();
    }

    @Override
    public R queryVersion(Integer id) {
        QueryInfo queryInfo = new QueryInfo();
        queryInfo.setBeanTime(new BeanTime(System.currentTimeMillis()));
        RealTimeData data = this.getById(id);
        log.info(" vin {}", data.getVin());
        EvGBProtocol protocol = new EvGBProtocol();
        protocol.setVin(data.getVin());
        protocol.setCommandType(QUERY_COMMAND);
        DataBody dataBody = new DataBody(queryInfo.encode());
        protocol.setBody(dataBody);
        protocol.setResponseType(ResponseType.COMMAND);
        Channel channel = CommonCache.vinChannelMap.get(data.getVin());
        if (channel == null) {
            return R.error("设备不在线");
        }
        queryHandler.sendQuery(protocol, CommonCache.vinChannelMap.get(data.getVin()));

        int timeout = 20;
        while (timeout > 0) {
            String info = CommonCache.queryMap.get(queryInfo.getBeanTime().formatTime() + queryInfo.getQuery());
            if (info != null) {
                return R.ok(info);
            } else {
                try {
                    Thread.sleep(500);
                    timeout--;
                } catch (InterruptedException e) {
                    return R.error(e.getMessage());
                }

            }
        }
        return R.error("未收到客户端回应");
    }

    /**
     * 获取地图数据
     * @return
     */
    @Override
    public List<RealTimeData> getAllForMap(){
        List<RealTimeData> realTimeDatas = baseMapper.selectList(new QueryWrapper<>());
        return realTimeDatas;
    }


    /**
     * 获取地图数据
     * @return
     */
    @Override
    public Map<String, String> getCountNow(){
        return baseMapper.getCountNow();
    }
}
